#ifndef ABSUI_PACKAGE_VIEW_HPP
#define ABSUI_PACKAGE_VIEW_HPP

#include "AbsUI/AbsUIConfig.hpp"
#include <boost/signals/trackable.hpp>

namespace Model { class Project; class Package; class Requirement; }
namespace Ctrl { class PackageController; }

namespace AbsUI
{
	
/// @ingroup AbsUI
/// @brief It provides the interface to be implemented by the views which need to display package related information.
///
/// A package view provides virtual methods that need to be overridden in order to treat signals fired by the package 
///	controller as a consequence of model changes.
class ABSUI_API PackageView: public boost::signals::trackable
{
public:
	/// @brief It initializes the view, by binding the signal handlers to the signals provided by the controller.
	/// @param rPackCtrler the controller object this view should bind its signal handlers to.
	PackageView( Ctrl::PackageController& rPackCtrler);

	/// @brief Dummy destructor.
	virtual ~PackageView() { }

	/// @brief It handles the case when a new package is added to an existing parent package.
	/// @param pParent the parent package.
	/// @param pNewPackage the new package, added as a child of the parent package.
	virtual void addNewPackage( Model::Package* pParent, Model::Package* pNewPackage) = 0;

	/// @brief It handles the case when an existing child package is removed from a parent package.
	/// @param pParent the parent package.
	/// @param pRemovedPackage the package that was removed from the parent package.
	virtual void removePackage( Model::Package* pParent, Model::Package* pRemovedPackage) = 0;

	/// @brief It handles the case when a root requirement is added to a package.
	/// @param pPackage the package containing the new root requirement.
	/// @param pAddedRequirement the requirement that was added.
	virtual void addRootRequirement( Model::Package* pParent, Model::Requirement* pAddedRequirement) = 0;

	/// @brief It handles the case wheh an existing root requirement is removed from a package.
	/// @param pPackage the package the root requirement was removed from.
	/// @param pRemovedRequirement the requirement that was removed.
	virtual void removeRootRequirement( Model::Package* pParent, Model::Requirement* pRemovedRequirement) = 0;

private:
	/// @brief It is the actual slot to be connected to the controller for handling the case of adding a new package to 
	///		an existing parent package.
	/// 
	/// It is implemented this way because connection to signals is done during view construction time and through 
	///	static binding, therefore the real handler 
	///	(AbsUI::PackageView::addNewPackage( Model::Package*, Model::Package*)) can't directly be bound. However, this 
	///	method does nothing else than calling the handler virtual method. Since calling of this method will always be 
	///	performed after the package view is fully constructed, the polymorphism will apply.
	void addNewPackageSlot( Model::Package* pParent, Model::Package* pNewPackage)
	{
		this->addNewPackage( pParent, pNewPackage);
	}

	/// @brief It is the actual slot to be connected to the controller for handling the case of removing an existing 
	///		child package from a parent package.
	/// 
	/// It is implemented this way because connection to signals is done during view construction time and through 
	///	static binding, therefore the real handler 
	///	(AbsUI::PackageView::removePackage( Model::Package*, Model::Package*)) can't directly be bound. However, this 
	///	method does nothing else than calling the handler virtual method. Since calling of this method will always be 
	///	performed after the package view is fully constructed, the polymorphism will apply.
	void removePackageSlot( Model::Package* pParent, Model::Package* pRemovedPackage)
	{
		this->removePackage( pParent, pRemovedPackage);
	}

	/// @brief It is the actual slot to be connected to the controller for handling the case of adding a new root
	///		requirement to an existing parent package.
	/// 
	/// It is implemented this way because connection to signals is done during view construction time and through 
	///	static binding, therefore the real handler 
	///	(AbsUI::PackageView::addRootRequirement( Model::Package*, Model::Requirement*)) can't directly be bound. 
	///	However, this method does nothing else than calling the handler virtual method. Since calling of this method 
	///	will always be performed after the package view is fully constructed, the polymorphism will apply.
	void addRootRequirementSlot( Model::Package* pParent, Model::Requirement* pRootRq)
	{
		this->addRootRequirement( pParent, pRootRq);
	}

	/// @brief It is the actual slot to be connected to the controller for handling the case of removing a root  
	///		requirement from an existing parent package.
	/// 
	/// It is implemented this way because connection to signals is done during view construction time and through 
	///	static binding, therefore the real handler 
	///	(AbsUI::PackageView::removeRootRequirement( Model::Package*, Model::Requirement*)) can't directly be bound. 
	///	However, this method does nothing else than calling the handler virtual method. Since calling of this method 
	///	will always be performed after the package view is fully constructed, the polymorphism will apply.
	void removeRootRequirementSlot( Model::Package* pParent, Model::Requirement* pRootRq)
	{
		this->removeRootRequirement( pParent, pRootRq);
	}

protected:
	Ctrl::PackageController& rPackageController_;

private:
	PackageView& operator=( PackageView& );
};

} // namespace AbsUI

#endif // ABSUI_PACKAGE_VIEW_HPP
